package com.linkoog.devtools.run_configuration;

import com.intellij.execution.ExecutionException;
import com.intellij.execution.RunConfigurationExtension;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.execution.configurations.RunConfigurationBase;
import com.intellij.execution.configurations.RunnerSettings;
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemRunConfiguration;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizerUtil;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.WriteExternalException;
import com.linkoog.devtools.run_configuration.ui.EnvFileEntry;
import com.linkoog.devtools.run_configuration.utils.ReadOnceMap;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class EnvFileRunConfigurationExtension extends RunConfigurationExtension {

    private static final Key<EnvFileSettings> USER_DATA_KEY = new Key<>("EnvFile Settings");

    @Nullable
    @Override
    protected String getEditorTitle() {
        return "EnvFile";
    }

    @NotNull
    @Override
    protected String getSerializationId() {
        return "com.linkoog.devtools.envfile";
    }

    @Nullable
    @Override
    protected <P extends RunConfigurationBase<?>> SettingsEditor<P> createEditor(@NotNull P configuration) {
        System.out.println("createEditor");
        return new EnvFileRunConfigurationEditor<P>(configuration);
    }

    @Override
    protected void readExternal(@NotNull RunConfigurationBase runConfiguration, @NotNull Element element) throws InvalidDataException {
        String isEnabledStr = JDOMExternalizerUtil.readField(element, "IS_ENABLED");
        boolean isEnabled = Boolean.parseBoolean(isEnabledStr);
        System.out.println("readExternal");
    }

    @Override
    protected void writeExternal(@NotNull RunConfigurationBase runConfiguration, @NotNull Element element) throws WriteExternalException {
        JDOMExternalizerUtil.writeField(element, "IS_ENABLED", Boolean.toString(true));
        System.out.println("writeExternal");
    }

    @Override
    protected void validateConfiguration(@NotNull RunConfigurationBase configuration, boolean isExecution) throws Exception {
        System.out.println("validateConfiguration");
    }

    /**
     * Unlike other extensions the IDEA extension
     * calls this method instead of RunConfigurationExtensionBase#patchCommandLine method
     * that we could have used to update environment variables.
     */
    @Override
    public <T extends RunConfigurationBase<?>> void updateJavaParameters(@NotNull final T configuration, @NotNull final JavaParameters params, final RunnerSettings runnerSettings) throws ExecutionException {
        /*EnvFileSettings envFileSetting = configuration.getUserData(USER_DATA_KEY);
        EnvFileEnvironmentVariables envFileEnvironmentVariables = new EnvFileEnvironmentVariables(envFileSetting);
        Map<String, String> newEnv = envFileEnvironmentVariables.render(configuration.getProject(), params.getEnv(), params.isPassParentEnvs());
        if (newEnv == null) {
            return;
        }*/

        Map<String, String> newEnv = new HashMap<>();
        // there is a chance that env is an immutable map,
        // that is why it is safer to replace it instead of updating it
        params.setEnv(new HashMap<>());

        // The code below works based on assumptions about internal implementation of
        // ExternalSystemExecuteTaskTask and ExternalSystemExecutionSettings and therefore may break any time may it change
        // It seems to be the only way to get things working for run configurations such as Gradle, at least for now
        if (isEnableExperimentalIntegrations(configuration)) {
            if (configuration instanceof ExternalSystemRunConfiguration) {
                ExternalSystemRunConfiguration ext = (ExternalSystemRunConfiguration) configuration;
                ext.getSettings().setEnv(new ReadOnceMap<>(newEnv, ext.getSettings().getEnv()));
            }
        }
    }

    public static boolean isEnableExperimentalIntegrations(@NotNull RunConfigurationBase<?> configuration) {
        EnvFileSettings state = configuration.getCopyableUserData(USER_DATA_KEY);
        return state != null && state.isEnableExperimentalIntegrations();
    }

     @Override
    public void attachToProcess(RunConfigurationBase configuration, ProcessHandler handler, RunnerSettings runnerSettings) {
        //val logPath = JitWatchSettings.getOrCreate(configuration).lastLogPath
        String logPath = "";
        if (logPath != null) {
            handler.addProcessListener( new  ProcessAdapter() {

                public void processTerminated(ProcessEvent event) {
                    ApplicationManager.getApplication().invokeLater(() ->{
                        //loadLogAndShowUI(configuration.getProject(), logPath);
                    });
                }
            });
        }
    }


    @Override
    public boolean isApplicableFor(@NotNull RunConfigurationBase configuration) {
        return true;
    }

    @Override
    public boolean isEnabledFor(@NotNull RunConfigurationBase applicableConfiguration, @Nullable RunnerSettings runnerSettings) {
        return true;
    }

}
